home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Graphics 2D / ZoomRecter / ZoomRecter.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  8.6 KB  |  365 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        ZoomRecter.c
  3.  
  4.     Contains:    This snippet shows how to do "Finder" style zooming between two rectangles.
  5.                 The boolean flag "kZoomLarger" controls the proportional direction of the
  6.                 zooming.
  7.     
  8.                 To get the two rectangles, you drag them out rubberbanded, and the zoom
  9.                 occurs between them.  To quit, click the close box.
  10.     
  11.                 If you want to do zooms between windows, open up a port with the dimensions
  12.                 of the desktop (from GetGrayRgn()).
  13.     
  14.                 DON'T use this as a sample of how to do rubberband drawing!!!  It's sort of
  15.                 hacked together bypassing the event mechanism and just using Button().
  16.  
  17.     Written by: SF    
  18.  
  19.     Copyright:    Copyright © 1992-1999 by Apple Computer, Inc., All Rights Reserved.
  20.  
  21.                 You may incorporate this Apple sample source code into your program(s) without
  22.                 restriction. This Apple sample source code has been provided "AS IS" and the
  23.                 responsibility for its operation is yours. You are not permitted to redistribute
  24.                 this Apple sample source code as "Apple sample source code" after having made
  25.                 changes. If you're going to re-distribute the source, we require that you make
  26.                 it clear in the source that the code was descended from Apple sample source
  27.                 code, but that you've made changes.
  28.  
  29.     Change History (most recent first):
  30.                 08/2000        JM                Carbonized, non-Carbon code is commented out
  31.                                             for demonstration purposes.  Changed basic code
  32.                                             significantly so it would simply work better.....
  33.                 7/14/1999    KG                Updated for Metrowerks Codewarror Pro 2.1
  34.                 
  35.  
  36. */
  37. #include "CarbonPrefix.h"
  38. #include <Dialogs.h>
  39. #include <Fonts.h>    
  40.  
  41. #define    kNumSteps        14
  42. #define    kRectsVisible    4
  43. #define    kZoomRatio        .7
  44. #define    kDelayTicks        1
  45.  
  46. #define    kZoomLarger        true        // change this to zoom "inward"
  47.  
  48.  
  49. void InitStuff(void);
  50. void ZoomRect(Boolean zoomOut,Rect *smallRect, Rect *bigRect);
  51. void CalcRect(Rect *theRect,Rect *smallRect,Rect *bigRect,double stepValue);
  52. //Boolean GetRects(Rect *zoomFrom,Rect *zoomTo);
  53. void FixRect(Rect *theRect,Rect *rightRect);
  54. void doEventLoop();
  55. void GetRect(Rect *zoomFrom, Rect *zoomTo);
  56.  
  57. Boolean gDone = false;
  58. WindowPtr gWindow;
  59.  
  60. void main(void)
  61. {
  62.     
  63.     Rect bounds = {44,12,330,500}/*,zoomFrom,zoomTo*/;
  64.     //Rect    tempRect1;    //used for carbonization
  65.         
  66.     InitStuff();
  67.     gWindow = NewWindow(nil,&bounds,"\pDrag Two Rects to Zoom",true,documentProc,(WindowPtr)-1L,true,0);
  68.     //SetPort(window);
  69.     SetPortWindowPort(gWindow);
  70.     
  71.     /*do {
  72.         if (GetRects(&zoomFrom,&zoomTo))
  73.             ZoomRect(kZoomLarger,&zoomFrom,&zoomTo);
  74.         //EraseRect(&window->portRect);
  75.         EraseRect(GetPortBounds(GetWindowPort(window), &tempRect1));
  76.     }
  77.     while (!gDone);*/
  78.     
  79.     doEventLoop();
  80.     
  81.     FlushEvents(everyEvent,0);
  82. }
  83.  
  84.     
  85. void InitStuff(void)
  86. {
  87.     //InitGraf(&qd.thePort);
  88.     //InitFonts();
  89.     //InitWindows();
  90.     //InitMenus();
  91.     //TEInit();
  92.     //InitDialogs(nil);
  93.     InitCursor();
  94.     FlushEvents(everyEvent,0);
  95. }
  96.  
  97.  
  98. void ZoomRect(Boolean zoomLarger,Rect *smallRect, Rect *bigRect)
  99. {
  100.     double firstStep,stepValue,trailer,zoomRatio;
  101.     short i,step;
  102.     Rect curRect;
  103.     unsigned long ticks;
  104.     Pattern    grayPattern; //used in carbonization
  105.     RgnHandle rgnHandle = NewRgn();
  106.     GrafPtr oldPort;
  107.     Rect    tempRect1;
  108.     
  109.     GetPort(&oldPort);
  110.     SetPort(GetWindowPort(gWindow));
  111.     
  112.     //PenPat(&qd.gray);
  113.     PenPat(GetQDGlobalsGray(&grayPattern));
  114.     PenMode(patXor);
  115.     
  116.     
  117.     firstStep=kZoomRatio;
  118.     for (i=0; i<kNumSteps; i++) {
  119.         firstStep *= kZoomRatio;
  120.     }
  121.  
  122.     if (!zoomLarger) {
  123.         zoomRatio = 1.0/kZoomRatio;
  124.         firstStep = 1.0-firstStep;
  125.     }
  126.     else
  127.         zoomRatio = kZoomRatio;
  128.         
  129.     trailer = firstStep;
  130.     stepValue = firstStep;
  131.     for (step=0; step<(kNumSteps+kRectsVisible); step++) {
  132.     
  133.         // draw new frame
  134.         
  135.         if (step<kNumSteps) {
  136.             stepValue /= zoomRatio;
  137.             CalcRect(&curRect,smallRect,bigRect,stepValue);
  138.             FrameRect(&curRect);
  139.         }
  140.         
  141.         // erase old frame
  142.         
  143.         if (step>=kRectsVisible) {
  144.             trailer /= zoomRatio;
  145.             CalcRect(&curRect,smallRect,bigRect,trailer);
  146.             FrameRect(&curRect);
  147.         }
  148.         QDFlushPortBuffer(GetWindowPort(gWindow), GetPortVisibleRegion(GetWindowPort(gWindow), rgnHandle));
  149.         Delay(kDelayTicks,&ticks);
  150.         
  151.     }
  152.  
  153.     PenNormal();
  154.     DisposeRgn(rgnHandle);
  155.     smallRect->top = bigRect->top = -1;
  156.     EraseRect(GetPortBounds(GetWindowPort(gWindow), &tempRect1));
  157.     
  158.     SetPort(oldPort);
  159. }
  160.  
  161.  
  162. void CalcRect(Rect *theRect,Rect *smallRect,Rect *bigRect,double stepValue)
  163. {
  164.     theRect->left = smallRect->left + (short)((double)(bigRect->left-smallRect->left)*stepValue);
  165.     theRect->top = smallRect->top + (short)((double)(bigRect->top-smallRect->top)*stepValue);
  166.     theRect->right = smallRect->right + (short)((double)(bigRect->right-smallRect->right)*stepValue);
  167.     theRect->bottom = smallRect->bottom + (short)((double)(bigRect->bottom-smallRect->bottom)*stepValue);
  168. }
  169.  
  170. // Old version, would require that you drag 2 rects before letting the event loop continue
  171. /*Boolean GetRects(Rect *zoomFrom,Rect *zoomTo)
  172. {
  173.     short numRects = 0;
  174.     //EventRecord ev;
  175.     Rect theRect,drawRect;
  176.     Point firstPt,curPt,oldPt,globalPt;
  177.     //KeyMap theKeys;
  178.     WindowPtr window;
  179.     Boolean result = true;
  180.     RgnHandle rgnHandle = NewRgn();
  181.     
  182.     PenMode(patXor);
  183.     
  184.     do {
  185.         while (!Button()) {
  186.         
  187.             GetMouse(&globalPt);
  188.             LocalToGlobal(&globalPt);
  189.             if ((FindWindow(globalPt,&window)==inGoAway) && window==FrontWindow()) {
  190.                 gDone = true;
  191.                 result = false;
  192.             }
  193.         
  194.             GetMouse(&firstPt);
  195.             oldPt = firstPt;
  196.             SetRect(&theRect,firstPt.h,firstPt.v,firstPt.h,firstPt.v);
  197.         }
  198.         
  199.         if (gDone)
  200.             break;
  201.         
  202.         while (Button()) {
  203.             GetMouse(&curPt);
  204.             if (!EqualPt(curPt,oldPt)) {
  205.                 FixRect(&theRect,&drawRect);
  206.                 FrameRect(&drawRect);
  207.                 oldPt = curPt;
  208.                 theRect.right = curPt.h;
  209.                 theRect.bottom = curPt.v;
  210.                 FixRect(&theRect,&drawRect);
  211.                 FrameRect(&drawRect);
  212.             }
  213.         }
  214.         
  215.         FixRect(&theRect,&drawRect);
  216.         if (numRects==0)
  217.             *zoomFrom = drawRect;
  218.         else
  219.             *zoomTo = drawRect;
  220.             
  221.         numRects++;
  222.         
  223.         QDFlushPortBuffer(GetWindowPort(window), GetPortVisibleRegion(GetWindowPort(window), rgnHandle));
  224.  
  225.     } while (numRects<2);
  226.     
  227.     PenNormal();
  228.     DisposeRgn(rgnHandle);
  229.     
  230.     return result;
  231. }*/
  232.  
  233. // New Version of GetRect(s), modified from original to only handle one dragged rect at a time.
  234.  
  235. void GetRect(Rect *zoomFrom, Rect *zoomTo)
  236. {
  237.     static short numRects = 0;
  238.     Rect theRect,drawRect;
  239.     Point firstPt,curPt,oldPt;
  240.     RgnHandle rgnHandle = NewRgn();
  241.     GrafPtr    oldPort;
  242.     
  243.     GetPort(&oldPort);
  244.     SetPort(GetWindowPort(gWindow));
  245.     
  246.     PenMode(patXor);
  247.     
  248.     GetMouse(&firstPt);
  249.     oldPt = firstPt;
  250.     SetRect(&theRect,firstPt.h,firstPt.v,firstPt.h,firstPt.v);
  251.     
  252.     while (Button()) {
  253.         GetMouse(&curPt);
  254.         if (!EqualPt(curPt,oldPt)) {
  255.             FixRect(&theRect,&drawRect);
  256.             FrameRect(&drawRect);
  257.             oldPt = curPt;
  258.             theRect.right = curPt.h;
  259.             theRect.bottom = curPt.v;
  260.             FixRect(&theRect,&drawRect);
  261.             FrameRect(&drawRect);
  262.             QDFlushPortBuffer(GetWindowPort(gWindow), GetPortVisibleRegion(GetWindowPort(gWindow), rgnHandle));
  263.         }
  264.     }
  265.         
  266.     FixRect(&theRect,&drawRect);
  267.     if (numRects==0)
  268.         *zoomFrom = drawRect;
  269.     else
  270.         *zoomTo = drawRect;
  271.             
  272.     numRects++;
  273.         
  274.     QDFlushPortBuffer(GetWindowPort(gWindow), GetPortVisibleRegion(GetWindowPort(gWindow), rgnHandle));
  275.     
  276.     if (numRects >= 2) {
  277.         ZoomRect(kZoomLarger, zoomFrom, zoomTo);
  278.         numRects = 0;
  279.     }
  280.     
  281.     PenNormal();
  282.     DisposeRgn(rgnHandle);
  283.     SetPort(oldPort);
  284.  
  285. }
  286.  
  287.  
  288. void FixRect(Rect *theRect,Rect *rightRect)
  289. {
  290.     if (theRect->right > theRect->left) {
  291.         rightRect->right = theRect->right;
  292.         rightRect->left = theRect->left;
  293.     }
  294.     else {
  295.         rightRect->right = theRect->left;
  296.         rightRect->left = theRect->right;
  297.     }
  298.     
  299.     if (theRect->bottom > theRect->top) {
  300.         rightRect->bottom = theRect->bottom;
  301.         rightRect->top = theRect->top;
  302.     }
  303.     else {
  304.         rightRect->bottom = theRect->top;
  305.         rightRect->top = theRect->bottom;
  306.     }
  307.     
  308. }
  309.  
  310. void doEventLoop()
  311. {
  312.     EventRecord anEvent;
  313.     WindowPtr   evtWind;
  314.     short       clickArea;
  315.     Rect        screenRect;
  316.     Point        thePoint;
  317.     Rect        zoomFrom, zoomTo;
  318.     
  319.     zoomFrom.top = zoomTo.top = -1;
  320.  
  321.     while (!gDone)
  322.     {
  323.         if (WaitNextEvent( everyEvent, &anEvent, 0, nil ))
  324.         {
  325.             if (anEvent.what == mouseDown)
  326.             {
  327.                 clickArea = FindWindow( anEvent.where, &evtWind );
  328.                 
  329.                 if (clickArea == inDrag)
  330.                 {
  331.                     GetRegionBounds( GetGrayRgn(), &screenRect );
  332.                     DragWindow( evtWind, anEvent.where, &screenRect );
  333.                 }
  334.                 else if (clickArea == inContent)
  335.                 {
  336.                     if (evtWind != FrontWindow())
  337.                         SelectWindow( evtWind );
  338.                     else
  339.                     {
  340.                         thePoint = anEvent.where;
  341.                         GlobalToLocal( &thePoint );
  342.                         //Handle click in window content here
  343.                         GetRect(&zoomFrom, &zoomTo);
  344.                     }
  345.                 }
  346.                 else if (clickArea == inGoAway)
  347.                     if (TrackGoAway( evtWind, anEvent.where ))
  348.                         gDone = true;
  349.             }
  350.             else if (anEvent.what == updateEvt)
  351.             {
  352.                 evtWind = (WindowPtr)anEvent.message;    
  353.                 SetPortWindowPort( evtWind );
  354.                 
  355.                 BeginUpdate( evtWind );
  356.                 //Call Draw Function here....
  357.                 if (zoomFrom.top != -1)
  358.                     FrameRect(&zoomFrom);
  359.                 if (zoomTo.top != -1)
  360.                     FrameRect(&zoomTo);
  361.                 EndUpdate (evtWind);
  362.             }
  363.         }
  364.     }
  365. }